Enhance geoniche to read the "real" geoniche binary format.
authoroliskoli <oliskoli@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Mon, 19 Dec 2005 22:44:15 +0000 (22:44 +0000)
committeroliskoli <oliskoli@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Mon, 19 Dec 2005 22:44:15 +0000 (22:44 +0000)
gpsbabel/geoniche.c

index 190c96ecb01f66566644883f64a725e8303ec1b8..4bc24931655406f5551ffaaf59dbffa8f5617013 100644 (file)
 #include "defs.h"
 #include "coldsync/palm.h"
 #include "coldsync/pdb.h"
+#include "garmin_tables.h"
+
+#include <math.h>
+#include <stdlib.h>
 
 #define MYNAME         "Geoniche"
-#define MYTYPE                 0x50454e44      /* PEND */
+#define MYTYPE_ASC     0x50454e44      /* PEND */
+#define MYTYPE_BIN     0x44415441      /* DATA */
 #define MYCREATOR      0x47656f4e      /* GeoN */
 
+#undef GEONICHE_DBG
+
 static FILE            *FileIn;
 static FILE            *FileOut;
 static const char      *FilenameOut;
@@ -180,17 +187,10 @@ eof:
 }
 
 static void
-data_read(void)
+geoniche_read_asc(const struct pdb *pdb)
 {
-    struct pdb *pdb;
     struct pdb_record *pdb_rec;
 
-    if (NULL == (pdb = pdb_Read(fileno(FileIn))))
-       fatal(MYNAME ": pdb_Read failed\n");
-
-    if ((pdb->creator != MYCREATOR) || (pdb->type != MYTYPE))
-       fatal(MYNAME ": Not a GeoNiche file.\n");
-
     /* Process record 0 */
     pdb_rec = pdb->rec_index.rec;
     if (strcmp((char *) pdb_rec->data, Rec0Magic))
@@ -326,7 +326,9 @@ data_read(void)
        tm.tm_mon -= 1;
        tm.tm_year -= 1900;
        sscanf(timestr, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
-       wpt->creation_time = mktime(&tm);
+       if (tm.tm_year >= 1970) {
+           wpt->creation_time = mktime(&tm);
+       }
        xfree(datestr);
        xfree(timestr);
 
@@ -352,6 +354,186 @@ data_read(void)
 
        waypt_add(wpt);
     } 
+}
+
+static char *geoniche_icon_map[] =                     /* MPS */
+{
+        /* 21 */ "Cross",
+        /* 22 */ "Cross (light)",                      
+        /* 23 */ "Cross (little)",
+        /* 24 */ "Cross (straight)",
+        /* 25 */ "Cross (light straight)",
+        /* 26 */ "Cross (little straight)",
+        /* 27 */ NULL,
+        /* 28 */ NULL,
+        /* 29 */ NULL,
+        /* 2A */ "Flag",
+        /* 2B */ "Car",                                /* 56 */
+        /* 2C */ "Gas Station",                        /* 8 */
+        /* 2D */ "Observation Point",
+        /* 2E */ "Scenic Area",                        /* 48 */
+        /* 2F */ "City",
+        /* 30 */ "Mountains",
+        /* 31 */ "Park",                               /* 46 */
+        /* 32 */ "Forest",                             /* 105 */
+        /* 33 */ "Campground",                         /* 38 */
+        /* 34 */ NULL,
+        /* 35 */ "Men",
+        /* 36 */ "Woman",
+        /* 37 */ "Hotel",                              /* 59 */
+        /* 38 */ "Residence",                          /* 10 */
+        /* 39 */ "Restaurant",                         /* 11 */
+        /* 3A */ "Cafe",
+        /* 3B */ NULL,
+        /* 3C */ "Airport",                            /* 107 */
+        /* 3D */ "Medical Facility",                   /* 43 */
+        /* 3E */ "Ropeway",
+        /* 3F */ "Sailing Area",
+        /* 40 */ "Anchor",
+        /* 41 */ NULL, /* Half Anchor ??? */
+        /* 42 */ "Fishing Area",                       /* 7 */
+        /* 43 */ "Stop Sign",
+        /* 44 */ "Question Sign",
+        /* 45 */ NULL,
+        /* 46 */ NULL,
+        /* 47 */ "Euro Sign",
+        /* 48 */ "Bank",                               /* 6 */
+        /* 49 */ NULL,
+        /* 4A */ "Left Arrow",
+        /* 4B */ "Right Arrow",
+        /* 4C */ "Traditional Cache",
+        /* 4D */ "Multi-Cache",                        /* 86 */
+        /* 4E */ "Virtual Cache",                      /* 48 */
+        /* 4F */ "Letterbox Cache",                    
+        /* 50 */ "Event Cache",                        /* 47 */
+        /* 51 */ "Webcam Cache",                       /* 90 */
+        /* 52 */ "Mystery or puzzle Cache",
+};
+
+static char *
+geoniche_icon_to_descr(const int no)
+{
+    char *result = NULL;
+
+    if (no >= 0x21) 
+    {
+       int i = no - 0x21;
+       if (i <= 49) 
+       {
+           result = geoniche_icon_map[i];
+       }
+    }
+    if (result != NULL) 
+    {
+       result = xstrdup(result);
+    }
+    return result;
+}
+
+static void
+geoniche_read_bin(const struct pdb *pdb)
+{
+    struct pdb_record *pdb_rec;
+    int ct = 0;
+    waypoint *waypt;
+
+    /* Process records */
+    
+    for (pdb_rec = pdb->rec_index.rec; pdb_rec != NULL; pdb_rec = pdb_rec->next)
+    {
+       char *vdata = (char *) pdb_rec->data;
+       int vlen = pdb_rec->data_len;
+       struct tm created, visited;
+       int i, icon_nr, selected;
+       int latdeg, londeg;
+       double lat, lon, altitude;
+       waypoint *waypt;
+       
+       memset(&visited, 0, sizeof(visited));
+       memset(&created, 0, sizeof(created));
+       
+       latdeg = be_read16(vdata + 0);
+       lat = be_read32(vdata + 2);
+       londeg = be_read16(vdata + 6);
+       lon = be_read32(vdata + 8);
+       altitude = (float) be_read32(vdata + 12);
+       selected = vdata[16];
+       created.tm_min = be_read16(vdata + 20);
+       created.tm_hour = be_read16(vdata + 22);
+       created.tm_mday = be_read16(vdata + 24);
+       created.tm_mon = be_read16(vdata + 26);
+       created.tm_year = be_read16(vdata + 28);
+       visited.tm_min = be_read16(vdata + 34);
+       visited.tm_hour = be_read16(vdata + 36);
+       visited.tm_mday = be_read16(vdata + 38);
+       visited.tm_mon = be_read16(vdata + 40);
+       visited.tm_year = be_read16(vdata + 42);
+
+#ifdef GEONICHE_DBG
+       printf(MYNAME "-date: %04d/%02d/%02d, %02d:%02d (%04d/%02d/%02d, %02d:%02d)\n", 
+           created.tm_year, created.tm_mon, created.tm_mday, created.tm_hour, created.tm_min,
+           visited.tm_year, visited.tm_mon, visited.tm_mday, visited.tm_hour, visited.tm_min);
+#endif
+       icon_nr = vdata[62];
+       
+       latdeg = 89 - latdeg;
+       lat = lat * (double) 0.0000006;
+       if (latdeg >= 0) 
+           lat = (double) 60.0 - lat;
+       else
+           latdeg++;
+
+       lon = lon * (double) 0.0000006;
+       while (londeg >= 360) londeg-=360;
+       if (londeg > 180)
+       {
+           lon = (double) 60.0 - lon;
+           londeg = londeg - 359;
+       }
+
+       created.tm_year-=1900;
+       created.tm_mon--;
+
+       waypt = waypt_new();
+       
+       waypt->shortname = xstrdup(vdata + 63);
+       waypt->altitude = altitude;
+       waypt->creation_time = mkgmtime(&created);
+       
+       GPS_Math_DegMin_To_Deg(latdeg, lat, &waypt->latitude);
+       GPS_Math_DegMin_To_Deg(londeg, lon, &waypt->longitude);
+       
+       waypt->icon_descr = geoniche_icon_to_descr(icon_nr);
+       if (waypt->icon_descr != NULL)
+               waypt->wpt_flags.icon_descr_is_dynamic = 1;
+       
+       waypt_add(waypt);
+    }
+}
+
+static void
+data_read(void)
+{
+    struct pdb *pdb;
+
+    if (NULL == (pdb = pdb_Read(fileno(FileIn))))
+       fatal(MYNAME ": pdb_Read failed\n");
+
+    if (pdb->creator != MYCREATOR)
+       fatal(MYNAME ": Not a GeoNiche file.\n");
+       
+    switch(pdb->type)
+    {
+       case MYTYPE_ASC:
+           geoniche_read_asc(pdb);
+           break;
+       case MYTYPE_BIN:
+           geoniche_read_bin(pdb);
+           break;
+       default:
+           fatal(MYNAME ": Unsupported GeoNiche file.\n");
+    }
+
     free_pdb(pdb);
 }
 
@@ -415,6 +597,7 @@ copilot_writewpt(const waypoint *wpt)
     char               timestr[8+1];
     char               *notes;
     int                        id;
+    time_t             tx;
 
     if (ct == 0)
     {
@@ -434,9 +617,16 @@ copilot_writewpt(const waypoint *wpt)
     if (id < 0)
        id = ct;
 
-    tm = *localtime(&wpt->creation_time);
-    strftime(datestr, sizeof(datestr), "%m/%d/%Y", &tm);
-    strftime(timestr, sizeof(timestr), "%H:%M:%S", &tm);
+    tx = (wpt->creation_time != 0) ? wpt->creation_time : gpsbabel_time;
+    if (tx == 0) {     /* maybe zero during testo (freezed time) */
+       strcpy(datestr, "01/01/1904");  /* this seems to be the uninitialized date value for geoniche */
+       strcpy(timestr, "00:00:00");
+    }
+    else  {
+       tm = *localtime(&tx);
+       strftime(datestr, sizeof(datestr), "%m/%d/%Y", &tm);
+       strftime(timestr, sizeof(timestr), "%H:%M:%S", &tm);
+    }
 
     /* Notes field MUST have soemthing in it */
     if (!wpt->notes || wpt->notes[0] == 0)
@@ -502,15 +692,18 @@ data_write(void)
     if (NULL == (PdbOut = new_pdb()))
        fatal (MYNAME ": new_pdb failed\n");
 
-    if (Arg_dbname)
+    if (Arg_dbname) {
+       if (case_ignore_strcmp(Arg_dbname, "GeoNiche Targets") == 0)
+           fatal(MYNAME ": Reserved database name!\n");
        strncpy(PdbOut->name, Arg_dbname, PDB_DBNAMELEN);
+    }
     else
        strncpy(PdbOut->name, FilenameOut, PDB_DBNAMELEN);
     PdbOut->name[PDB_DBNAMELEN-1] = 0;
 
     PdbOut->attributes = PDB_ATTR_BACKUP;
     PdbOut->ctime = PdbOut->mtime = current_time() + (49*365 + 17*366) * (60*60*24);
-    PdbOut->type = MYTYPE;
+    PdbOut->type = MYTYPE_ASC;
     PdbOut->creator = MYCREATOR; 
     PdbOut->version = 0;
     PdbOut->modnum = 1;
@@ -535,5 +728,5 @@ ff_vecs_t geoniche_vecs =
        data_write,
        NULL, 
        Args,
-       CET_CHARSET_ASCII, 0    /* CET-REVIEW */
+       CET_CHARSET_MS_ANSI, 0  /* CET-REVIEW */
 };